package cc.xpcas.raft.role;

import cc.xpcas.raft.Configuration;
import cc.xpcas.raft.context.Context;
import cc.xpcas.raft.message.*;

/**
 * @author xp
 */
public abstract class Role {

    private final Context context;

    public Role(Context context) {
        this.context = context;
    }

    public Context getContext() {
        return context;
    }

    public Configuration getConfiguration() {
        return context.getConfiguration();
    }

    /**
     * in mainline
     */
    public abstract void start();

    /**
     * in mainline
     */
    public abstract void end() throws InterruptedException;

    /**
     * in mainline
     */
    public abstract boolean handleAppendEntriesRequest(MessageContext messageContext) throws InterruptedException;

    /**
     * in mainline
     */
    public boolean handleAppendEntriesResponse(MessageContext messageContext) throws InterruptedException {
        // ignore if we're not leader yet
        return true;
    }

    private boolean isNewTermCandidate(long term) {
        return getContext().catchUpTerm(term) < 0;
    }

    /**
     * in mainline
     */
    public boolean handleRequestVoteRequest(MessageContext messageContext) throws InterruptedException {
        RequestVoteRequest message = messageContext.getMessage();
        if (isNewTermCandidate(message.getTerm())) {
            return false;
        }
        return true;
    }

    /**
     * in mainline
     */
    public boolean handleRequestVoteResponse(MessageContext messageContext) throws InterruptedException {
        // ignore if we're not candidate yet
        return true;
    }
}
